﻿using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Reactive.Concurrency;
using System.Reactive.Subjects;

namespace System.Reactive.Linq
{
	public static partial class Observable
	{
		public static IObservable<TResult> Generate<TState, TResult>(TState initialState, Func<TState, bool> condition, Func<TState, TState> iterate, Func<TState, TResult> resultSelector)
		{
			Contract.Requires(condition != null, null, "condition != null");
			Contract.Requires(iterate != null, null, "iterate != null");
			Contract.Requires(resultSelector != null, null, "resultSelector != null");
			Contract.Ensures(Contract.Result<IObservable<TResult>>() != null, null, "Contract.Result<IObservable<TResult>>() != null");
			return null;
		}

		public static IObservable<TResult> Generate<TState, TResult>(TState initialState, Func<TState, bool> condition, Func<TState, TState> iterate, Func<TState, TResult> resultSelector, Func<TState, DateTimeOffset> timeSelector)
		{
			Contract.Requires(condition != null, null, "condition != null");
			Contract.Requires(iterate != null, null, "iterate != null");
			Contract.Requires(resultSelector != null, null, "resultSelector != null");
			Contract.Requires(timeSelector != null, null, "timeSelector != null");
			Contract.Ensures(Contract.Result<IObservable<TResult>>() != null, null, "Contract.Result<IObservable<TResult>>() != null");
			return null;
		}

		public static IObservable<TResult> Generate<TState, TResult>(TState initialState, Func<TState, bool> condition, Func<TState, TState> iterate, Func<TState, TResult> resultSelector, Func<TState, TimeSpan> timeSelector)
		{
			Contract.Requires(condition != null, null, "condition != null");
			Contract.Requires(iterate != null, null, "iterate != null");
			Contract.Requires(resultSelector != null, null, "resultSelector != null");
			Contract.Requires(timeSelector != null, null, "timeSelector != null");
			Contract.Ensures(Contract.Result<IObservable<TResult>>() != null, null, "Contract.Result<IObservable<TResult>>() != null");
			return null;
		}

		public static IObservable<TResult> Generate<TState, TResult>(TState initialState, Func<TState, bool> condition, Func<TState, TState> iterate, Func<TState, TResult> resultSelector, IScheduler scheduler)
		{
			Contract.Requires(condition != null, null, "condition != null");
			Contract.Requires(iterate != null, null, "iterate != null");
			Contract.Requires(resultSelector != null, null, "resultSelector != null");
			Contract.Requires(scheduler != null, null, "scheduler != null");
			Contract.Ensures(Contract.Result<IObservable<TResult>>() != null, null, "Contract.Result<IObservable<TResult>>() != null");
			return null;
		}

		public static IObservable<TResult> Generate<TState, TResult>(TState initialState, Func<TState, bool> condition, Func<TState, TState> iterate, Func<TState, TResult> resultSelector, Func<TState, DateTimeOffset> timeSelector, IScheduler scheduler)
		{
			Contract.Requires(condition != null, null, "condition != null");
			Contract.Requires(iterate != null, null, "iterate != null");
			Contract.Requires(resultSelector != null, null, "resultSelector != null");
			Contract.Requires(timeSelector != null, null, "timeSelector != null");
			Contract.Requires(scheduler != null, null, "scheduler != null");
			Contract.Ensures(Contract.Result<IObservable<TResult>>() != null, null, "Contract.Result<IObservable<TResult>>() != null");
			return null;
		}

		public static IObservable<TResult> Generate<TState, TResult>(TState initialState, Func<TState, bool> condition, Func<TState, TState> iterate, Func<TState, TResult> resultSelector, Func<TState, TimeSpan> timeSelector, IScheduler scheduler)
		{
			Contract.Requires(condition != null, null, "condition != null");
			Contract.Requires(iterate != null, null, "iterate != null");
			Contract.Requires(resultSelector != null, null, "resultSelector != null");
			Contract.Requires(timeSelector != null, null, "timeSelector != null");
			Contract.Requires(scheduler != null, null, "scheduler != null");
			Contract.Ensures(Contract.Result<IObservable<TResult>>() != null, null, "Contract.Result<IObservable<TResult>>() != null");
			return null;
		}

		public static AsyncSubject<TSource> GetAwaiter<TSource>(this IObservable<TSource> source)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Ensures(Contract.Result<AsyncSubject<TSource>>() != null, null, "Contract.Result<AsyncSubject<TSource>>() != null");
			return null;
		}

		public static AsyncSubject<TSource> GetAwaiter<TSource>(this IConnectableObservable<TSource> source)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Ensures(Contract.Result<AsyncSubject<TSource>>() != null, null, "Contract.Result<AsyncSubject<TSource>>() != null");
			return null;
		}

		public static IEnumerator<TSource> GetEnumerator<TSource>(this IObservable<TSource> source)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Ensures(Contract.Result<IEnumerator<TSource>>() != null, null, "Contract.Result<IEnumerator<TSource>>() != null");
			return null;
		}

		public static IObservable<IGroupedObservable<TKey, TSource>> GroupBy<TSource, TKey>(this IObservable<TSource> source, Func<TSource, TKey> keySelector)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(keySelector != null, null, "keySelector != null");
			Contract.Ensures(Contract.Result<IObservable<IGroupedObservable<TKey, TSource>>>() != null, null, "Contract.Result<IObservable<IGroupedObservable<TKey, TSource>>>() != null");
			return null;
		}

		public static IObservable<IGroupedObservable<TKey, TElement>> GroupBy<TSource, TKey, TElement>(this IObservable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(keySelector != null, null, "keySelector != null");
			Contract.Requires(elementSelector != null, null, "elementSelector != null");
			Contract.Ensures(Contract.Result<IObservable<IGroupedObservable<TKey, TElement>>>() != null, null, "Contract.Result<IObservable<IGroupedObservable<TKey, TElement>>>() != null");
			return null;
		}

		public static IObservable<IGroupedObservable<TKey, TSource>> GroupBy<TSource, TKey>(this IObservable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(keySelector != null, null, "keySelector != null");
			Contract.Requires(comparer != null, null, "comparer != null");
			Contract.Ensures(Contract.Result<IObservable<IGroupedObservable<TKey, TSource>>>() != null, null, "Contract.Result<IObservable<IGroupedObservable<TKey, TSource>>>() != null");
			return null;
		}

		public static IObservable<IGroupedObservable<TKey, TElement>> GroupBy<TSource, TKey, TElement>(this IObservable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(keySelector != null, null, "keySelector != null");
			Contract.Requires(elementSelector != null, null, "elementSelector != null");
			Contract.Requires(comparer != null, null, "comparer != null");
			Contract.Ensures(Contract.Result<IObservable<IGroupedObservable<TKey, TElement>>>() != null, null, "Contract.Result<IObservable<IGroupedObservable<TKey, TElement>>>() != null");
			return null;
		}

		public static IObservable<IGroupedObservable<TKey, TSource>> GroupByUntil<TSource, TKey, TDuration>(this IObservable<TSource> source, Func<TSource, TKey> keySelector, Func<IGroupedObservable<TKey, TSource>, IObservable<TDuration>> durationSelector)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(keySelector != null, null, "keySelector != null");
			Contract.Requires(durationSelector != null, null, "durationSelector != null");
			Contract.Ensures(Contract.Result<IObservable<IGroupedObservable<TKey, TSource>>>() != null, null, "Contract.Result<IObservable<IGroupedObservable<TKey, TSource>>>() != null");
			return null;
		}

		public static IObservable<IGroupedObservable<TKey, TSource>> GroupByUntil<TSource, TKey, TDuration>(this IObservable<TSource> source, Func<TSource, TKey> keySelector, Func<IGroupedObservable<TKey, TSource>, IObservable<TDuration>> durationSelector, IEqualityComparer<TKey> comparer)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(keySelector != null, null, "keySelector != null");
			Contract.Requires(durationSelector != null, null, "durationSelector != null");
			Contract.Requires(comparer != null, null, "comparer != null");
			Contract.Ensures(Contract.Result<IObservable<IGroupedObservable<TKey, TSource>>>() != null, null, "Contract.Result<IObservable<IGroupedObservable<TKey, TSource>>>() != null");
			return null;
		}

		public static IObservable<IGroupedObservable<TKey, TElement>> GroupByUntil<TSource, TKey, TElement, TDuration>(this IObservable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, Func<IGroupedObservable<TKey, TElement>, IObservable<TDuration>> durationSelector)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(keySelector != null, null, "keySelector != null");
			Contract.Requires(elementSelector != null, null, "elementSelector != null");
			Contract.Requires(durationSelector != null, null, "durationSelector != null");
			Contract.Ensures(Contract.Result<IObservable<IGroupedObservable<TKey, TElement>>>() != null, null, "Contract.Result<IObservable<IGroupedObservable<TKey, TElement>>>() != null");
			return null;
		}

		public static IObservable<IGroupedObservable<TKey, TElement>> GroupByUntil<TSource, TKey, TElement, TDuration>(this IObservable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, Func<IGroupedObservable<TKey, TElement>, IObservable<TDuration>> durationSelector, IEqualityComparer<TKey> comparer)
		{
			Contract.Requires(source != null, null, "source != null");
			Contract.Requires(keySelector != null, null, "keySelector != null");
			Contract.Requires(elementSelector != null, null, "elementSelector != null");
			Contract.Requires(durationSelector != null, null, "durationSelector != null");
			Contract.Requires(comparer != null, null, "comparer != null");
			Contract.Ensures(Contract.Result<IObservable<IGroupedObservable<TKey, TElement>>>() != null, null, "Contract.Result<IObservable<IGroupedObservable<TKey, TElement>>>() != null");
			return null;
		}

		public static IObservable<TResult> GroupJoin<TLeft, TRight, TLeftDuration, TRightDuration, TResult>(this IObservable<TLeft> left, IObservable<TRight> right, Func<TLeft, IObservable<TLeftDuration>> leftDurationSelector, Func<TRight, IObservable<TRightDuration>> rightDurationSelector, Func<TLeft, IObservable<TRight>, TResult> resultSelector)
		{
			Contract.Requires(left != null, null, "left != null");
			Contract.Requires(right != null, null, "right != null");
			Contract.Requires(leftDurationSelector != null, null, "leftDurationSelector != null");
			Contract.Requires(rightDurationSelector != null, null, "rightDurationSelector != null");
			Contract.Requires(resultSelector != null, null, "resultSelector != null");
			Contract.Ensures(Contract.Result<IObservable<TResult>>() != null, null, "Contract.Result<IObservable<TResult>>() != null");
			return null;
		}
	}
}